import { Repository, FindOptionsWhere, FindManyOptions, SelectQueryBuilder, DeepPartial } from 'typeorm';
import { Injectable, NotFoundException } from '@nestjs/common';
import { BaseEntity } from '../entity/base.entity';
import { PaginationDto, PaginationResponseDto } from '../dto/pagination.dto';

/**
 * 日志记录接口
 */
export interface ILoggableService {
  getResourceType(): string;
  getResourceName(): string;
  logCreate(userId?: string, resourceId?: string): Promise<void>;
  logUpdate(userId?: string, resourceId?: string): Promise<void>;
  logDelete(userId?: string, resourceId?: string): Promise<void>;
  logBatchDelete(userId?: string, resourceIds?: string[]): Promise<void>;
}

@Injectable()
export abstract class BaseService<T extends BaseEntity> implements ILoggableService {
  constructor(protected readonly repository: Repository<T>) {}

  /**
   * 获取资源类型名称（子类可以重写）
   */
  public getResourceType(): string {
    return 'entity';
  }

  /**
   * 获取资源名称（子类可以重写）
   */
  public getResourceName(): string {
    return '实体';
  }

  /**
   * 记录创建日志（子类可以重写）
   */
  public async logCreate(userId?: string, resourceId?: string): Promise<void> {
    // 默认实现为空，子类可以重写
  }

  /**
   * 记录更新日志（子类可以重写）
   */
  public async logUpdate(userId?: string, resourceId?: string): Promise<void> {
    // 默认实现为空，子类可以重写
  }

  /**
   * 记录删除日志（子类可以重写）
   */
  public async logDelete(userId?: string, resourceId?: string): Promise<void> {
    // 默认实现为空，子类可以重写
  }

  /**
   * 记录批量删除日志（子类可以重写）
   */
  public async logBatchDelete(userId?: string, resourceIds?: string[]): Promise<void> {
    // 默认实现为空，子类可以重写
  }

  /**
   * 创建实体
   */
  async create(data: DeepPartial<T>, userId?: string): Promise<boolean> {
    try {
      const entity = this.repository.create(data);
      
      // 时间字段现在由 @BeforeInsert 钩子自动设置
      const savedEntity = await this.repository.save(entity);
      
      // 记录创建日志
      await this.logCreate(userId, savedEntity.id);
      
      return true;
    } catch (error) {
      return false;
    }
  }

  /**
   * 根据ID查找实体
   */
  async findById(id: string): Promise<T> {
    const entity = await this.repository.findOne({
      where: { id, isDeleted: false } as FindOptionsWhere<T>,
    });
    if (!entity) {
      throw new NotFoundException(`实体不存在: ${id}`);
    }
    return entity;
  }

  /**
   * 查找所有实体
   */
  async findAll(options?: FindManyOptions<T>): Promise<T[]> {
    const defaultOptions: FindManyOptions<T> = {
      where: { isDeleted: false } as FindOptionsWhere<T>,
      ...options,
    };
    return await this.repository.find(defaultOptions);
  }

  /**
   * 分页查询
   */
  async findWithPagination(
    paginationDto: PaginationDto,
    options?: FindManyOptions<T>,
  ): Promise<PaginationResponseDto<T>> {
    const { page = 1, pageSize = 10, sortBy, sortOrder = 'DESC' } = paginationDto;

    const defaultOptions: FindManyOptions<T> = {
      where: { isDeleted: false } as FindOptionsWhere<T>,
      skip: (page - 1) * pageSize,
      take: pageSize,
      ...options,
    };

    // 添加排序
    if (sortBy) {
      defaultOptions.order = { [sortBy]: sortOrder } as any;
    } else {
      defaultOptions.order = { createdAt: sortOrder } as any;
    }

    const [data, total] = await this.repository.findAndCount(defaultOptions);

    return {
      data,
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize),
      hasNext: page < Math.ceil(total / pageSize),
      hasPrev: page > 1,
    };
  }

  /**
   * 更新实体
   */
  async update(id: string, data: Partial<T>, userId?: string): Promise<boolean> {
    try {
      const entity = await this.findById(id);
      Object.assign(entity, data);
      
      // 时间字段现在由 @BeforeUpdate 钩子自动设置
      await this.repository.save(entity);
      
      // 记录更新日志
      await this.logUpdate(userId, id);
      
      return true;
    } catch (error) {
      return false;
    }
  }

  /**
   * 删除实体（软删除）
   */
  async delete(id: string, userId?: string): Promise<boolean> {
    try {
      const entity = await this.findById(id);
      entity.isDeleted = true;
      
      // 时间字段现在由 @BeforeUpdate 钩子自动设置
      await this.repository.save(entity);
      
      // 记录删除日志
      await this.logDelete(userId, id);
      
      return true;
    } catch (error) {
      return false;
    }
  }

  /**
   * 批量删除
   */
  async batchDelete(ids: string[], userId?: string): Promise<boolean> {
    try {
      const entities = await this.repository.find({
        where: { id: ids as any, isDeleted: false } as FindOptionsWhere<T>,
      });

      if (entities.length !== ids.length) {
        return false;
      }

      for (const entity of entities) {
        entity.isDeleted = true;
        
        // 时间字段现在由 @BeforeUpdate 钩子自动设置
      }

      await this.repository.save(entities);
      
      // 记录批量删除日志
      await this.logBatchDelete(userId, ids);
      
      return true;
    } catch (error) {
      return false;
    }
  }

  /**
   * 检查实体是否存在
   */
  async exists(id: string): Promise<boolean> {
    const count = await this.repository.count({
      where: { id, isDeleted: false } as FindOptionsWhere<T>,
    });
    return count > 0;
  }

  /**
   * 获取查询构建器
   */
  protected createQueryBuilder(alias?: string): SelectQueryBuilder<T> {
    return this.repository.createQueryBuilder(alias);
  }

  /**
   * 根据条件查找单个实体
   */
  async findOne(where: FindOptionsWhere<T>): Promise<T | null> {
    return await this.repository.findOne({
      where: { ...where, isDeleted: false } as FindOptionsWhere<T>,
    });
  }

  /**
   * 根据条件查找多个实体
   */
  async findMany(where: FindOptionsWhere<T>): Promise<T[]> {
    return await this.repository.find({
      where: { ...where, isDeleted: false } as FindOptionsWhere<T>,
    });
  }
} 